#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdlib>
#include <ctime>
#include "Task.hpp"
#include "BlockQueue.hpp"
using namespace std;
#define PthreadNUM 3
#define CthreadNUM 3

pthread_mutex_t stdoutlock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t stdoutcond = PTHREAD_COND_INITIALIZER;

void *producer(void *argv)
{
    int len = opers.size();
    BlockQueue<Task, 5> *bq = (BlockQueue<Task, 5> *)argv;
    while (true)
    {
        int data1 = rand() % 10;
        int data2 = rand() % 10;
        char oper = opers[rand() % len];
        Task task(data1, data2, oper);
        bq->push(task);
        pthread_mutex_lock(&stdoutlock);
        // pthread_cond_wait(&stdoutcond,&stdoutlock);
        cout << "Produced: " << task.getTask() << endl;
        // cout <<  task.getTask() << endl;
        pthread_mutex_unlock(&stdoutlock);
        sleep(2);
    }
    return nullptr;
}

void *consumer(void *argv)
{
    BlockQueue<Task, 5> *bq = (BlockQueue<Task, 5> *)argv;
    while (true)
    {
        Task task = bq->pop();
        task();
        pthread_mutex_lock(&stdoutlock);
        cout << "Consumed: " << task.getResult() << endl;
        pthread_mutex_unlock(&stdoutlock);
    }
    return nullptr;
}

int main()
{
    srand(time(nullptr));
    BlockQueue<Task, 5> *bq = new BlockQueue<Task, 5>();
    pthread_t c[3], p[3];
    for (int i = 0; i < PthreadNUM; i++)
    {
        pthread_create(&p[i], nullptr, producer, bq);
    }
    for (int i = 0; i < CthreadNUM; i++)
    {
        pthread_create(&c[i], nullptr, consumer, bq);
    }
    for (int i = 0; i < PthreadNUM; i++)
    {
        pthread_join(p[i], nullptr);
    }
    for (int i = 0; i < CthreadNUM; i++)
    {
        pthread_join(c[i], nullptr);
    }
    return 0;
}